package jus.poc.prodcons.v6;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.InvalidPropertiesFormatException;
import java.util.Map;
import java.util.Properties;
import jus.poc.prodcons.Observateur;
import jus.poc.prodcons.Simulateur;

/**
 * Classe principale permettant de lancer l'application
 *
 * @author Nunes Thomas <nds.thomas@gmail.com>
 * @author Feng Xu <fengxu1989@gmail.com>
 */
public class TestProdCons extends Simulateur {

    /**
     * Numero de version de l'application
     */
    protected final int objectif = 6;
    protected int nbProd;
    protected int nbCons;
    protected int nbBuffer;
    protected int tempsMoyenProduction;
    protected int deviationTempsMoyenProduction;
    protected int tempsMoyenConsommation;
    protected int deviationTempsMoyenConsommation;
    protected int nombreMoyenDeProduction;
    protected int deviationNombreMoyenDeProduction;
    protected int nombreMoyenNbExemplaire;
    protected int deviationNombreMoyenNbExemplaire;

    public TestProdCons(Observateur observateur) {
        super(observateur);
    }

    @Override
    protected void run() throws Exception {
        int messagesEnAttente = 0,messagesEchanges = 0;
        init("jus/poc/prodcons/options/option6.xml");
        observateur.init(nbProd, nbCons, nbBuffer);
        ProdCons tampon = new ProdCons(nbBuffer);
        Producteur[] producteurs = new Producteur[nbProd];
        for (int i = 0; i < producteurs.length; i++) {
            producteurs[i] = new Producteur(observateur, tempsMoyenProduction, deviationTempsMoyenProduction, tampon, nombreMoyenDeProduction, deviationNombreMoyenDeProduction, i);
            observateur.newProducteur(producteurs[i]);
            producteurs[i].start();
            messagesEnAttente += producteurs[i].nbMessages;

        }
        Consommateur[] consommateurs = new Consommateur[nbCons];
        for (int i = 0; i < consommateurs.length; i++) {
            consommateurs[i] = new Consommateur(observateur, tempsMoyenConsommation, deviationTempsMoyenConsommation, tampon, i);
            observateur.newConsommateur(consommateurs[i]);
            consommateurs[i].setDaemon(true);
            consommateurs[i].start();
        }

        while (messagesEnAttente != messagesEchanges) {
            messagesEchanges = 0;
            for (int i = 0; i < consommateurs.length; i++) {
                messagesEchanges += consommateurs[i].nombreDeMessages();
            }
        }
        SimpleDateFormat formatDate = new SimpleDateFormat("MM/dd/yyyy 'a' HH:mm:ss:S ");
 
                System.out.println("\n\n@@@@@@ OBJECTIF" + this.objectif + " @@@@@@");
        System.out.println(" Date de fin: " + formatDate.format(new Date()));
        System.out.println("Nombre de message échangés:" + messagesEchanges);
        
        if (observateur.coherent()) {
            System.out.println("Remarque : l'observateur a approuve le fonctionnement de l'application");
        } else {
            System.out.println("Remarque : l'observateur n'a pas approuve le fonctionnement de l'application");
        }

    }

    /**
     * Retreave the parameters of the application.
     *
     * @param file the final name of the file containing the options.
     */
    protected void init(String file) {

        Properties properties = new Properties();
        try {
            properties.loadFromXML(ClassLoader.getSystemResourceAsStream(file));
        } catch (InvalidPropertiesFormatException e) {
        } catch (IOException e) {
        }
        String key;
        int value;
        Class<?> thisOne = getClass();
        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            key = (String) entry.getKey();
            value = Integer.parseInt((String) entry.getValue());
            try {
                thisOne.getDeclaredField(key).set(this, value);
            } catch (IllegalArgumentException | IllegalAccessException | SecurityException e) {
            } catch (NoSuchFieldException e) {
                System.out.println("Exception: Version non conforme avec les paramètres.");
            }
        }
    }

    public static void main(String[] args) {
        new TestProdCons(new Observateur()).start();
    }
}
